package com.kexio.dynamic.datasource.service.impl;

import com.kexio.dynamic.datasource.service.DataSourceSwitchService;
import com.kexio.dynamic.datasource.service.DynamicDataSourceService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 数据源切换服务默认实现
 * 
 * @author Kexio
 * @since 1.0.0
 */
@Service
public class DefaultDataSourceSwitchService implements DataSourceSwitchService {

    private static final Logger log = LoggerFactory.getLogger(DefaultDataSourceSwitchService.class);

    private final DynamicDataSourceService dynamicDataSourceService;
    private final ExpressionParser expressionParser = new SpelExpressionParser();
    private final Random random = new Random();
    
    // 数据源切换计数器（用于轮询负载均衡）
    private final Map<String, AtomicInteger> roundRobinCounters = new ConcurrentHashMap<>();
    
    // 线程本地数据源存储
    private static final ThreadLocal<String> currentDataSource = new ThreadLocal<>();
    
    private static final String DEFAULT_DS = "master";
    private static final String MASTER_DS = "master";
    private static final String SLAVE_PREFIX = "slave";

    public DefaultDataSourceSwitchService(DynamicDataSourceService dynamicDataSourceService) {
        this.dynamicDataSourceService = dynamicDataSourceService;
    }

    @Override
    public void switchTo(String dataSourceName) {
        if (!StringUtils.hasText(dataSourceName)) {
            log.warn("数据源名称为空，使用默认数据源");
            dataSourceName = DEFAULT_DS;
        }
        
        // 检查数据源是否存在
        if (!dynamicDataSourceService.exists(dataSourceName)) {
            log.warn("数据源不存在: {}，回退到默认数据源", dataSourceName);
            dataSourceName = DEFAULT_DS;
        }
        
        currentDataSource.set(dataSourceName);
        log.debug("切换到数据源: {}", dataSourceName);
    }

    @Override
    public void switchToMaster() {
        switchTo(MASTER_DS);
    }

    @Override
    public void switchToSlave() {
        String slaveDs = selectSlave();
        switchTo(slaveDs);
    }

    @Override
    public void switchToTenant(Long tenantId) {
        if (tenantId == null || tenantId <= 0) {
            log.warn("租户ID无效: {}，使用默认数据源", tenantId);
            switchTo(DEFAULT_DS);
            return;
        }
        
        String tenantDs = "tenant_" + tenantId;
        switchTo(tenantDs);
    }

    @Override
    public String getCurrentDataSource() {
        String ds = currentDataSource.get();
        return StringUtils.hasText(ds) ? ds : DEFAULT_DS;
    }

    @Override
    public void reset() {
        switchTo(DEFAULT_DS);
    }

    @Override
    public void clear() {
        currentDataSource.remove();
        log.debug("清除当前线程数据源设置");
    }

    @Override
    public boolean exists(String dataSourceName) {
        return dynamicDataSourceService.exists(dataSourceName);
    }

    @Override
    public String getDefaultDataSource() {
        return DEFAULT_DS;
    }

    @Override
    public boolean isMaster(String dataSourceName) {
        return MASTER_DS.equals(dataSourceName);
    }

    @Override
    public boolean isSlave(String dataSourceName) {
        return dataSourceName != null && dataSourceName.startsWith(SLAVE_PREFIX);
    }

    @Override
    public boolean isTenant(String dataSourceName) {
        return dataSourceName != null && dataSourceName.startsWith("tenant_");
    }

    @Override
    public Set<String> getAvailableDataSources() {
        return dynamicDataSourceService.getCurrentDataSources();
    }

    @Override
    public Set<String> getSlaveDataSources() {
        return getAvailableDataSources().stream()
                .filter(this::isSlave)
                .collect(java.util.stream.Collectors.toSet());
    }

    @Override
    public String selectSlave() {
        return selectSlave("round_robin");
    }

    @Override
    public String selectSlave(String strategy) {
        Set<String> slaveDSs = getSlaveDataSources();
        
        if (slaveDSs.isEmpty()) {
            log.warn("没有可用的从库，使用主库");
            return MASTER_DS;
        }
        
        switch (strategy.toLowerCase()) {
            case "random":
                return selectSlaveRandom(slaveDSs);
            case "round_robin":
            default:
                return selectSlaveRoundRobin(slaveDSs);
        }
    }

    @Override
    public String resolveDataSourceExpression(String expression) {
        if (!StringUtils.hasText(expression)) {
            return DEFAULT_DS;
        }
        
        // 如果不包含表达式语法，直接返回
        if (!expression.contains("${") && !expression.contains("#{")) {
            return expression;
        }
        
        try {
            // 创建评估上下文
            EvaluationContext context = createEvaluationContext();
            
            // 解析表达式
            Expression expr = expressionParser.parseExpression(expression);
            Object result = expr.getValue(context);
            
            return result != null ? result.toString() : DEFAULT_DS;
            
        } catch (Exception e) {
            log.warn("数据源表达式解析失败: {}", expression, e);
            return DEFAULT_DS;
        }
    }

    /**
     * 随机选择从库
     */
    private String selectSlaveRandom(Set<String> slaveDSs) {
        String[] slaves = slaveDSs.toArray(new String[0]);
        return slaves[random.nextInt(slaves.length)];
    }

    /**
     * 轮询选择从库
     */
    private String selectSlaveRoundRobin(Set<String> slaveDSs) {
        String[] slaves = slaveDSs.toArray(new String[0]);
        String key = "slave_group";
        
        AtomicInteger counter = roundRobinCounters.computeIfAbsent(key, k -> new AtomicInteger(0));
        int index = counter.getAndIncrement() % slaves.length;
        
        return slaves[index];
    }

    /**
     * 创建SpEL表达式评估上下文
     */
    private EvaluationContext createEvaluationContext() {
        StandardEvaluationContext context = new StandardEvaluationContext();
        
        // 添加变量
        try {
            // 添加当前用户信息
            // Long userId = UserInfoUtils.getCurrentUserId();
            // Long tenantId = UserInfoUtils.getCurrentTenantId();
            // context.setVariable("userId", userId);
            // context.setVariable("tenantId", tenantId);
            
            // 添加系统信息
            context.setVariable("timestamp", System.currentTimeMillis());
            context.setVariable("env", getActiveProfile());
            
        } catch (Exception e) {
            log.debug("创建表达式上下文时获取用户信息失败", e);
        }
        
        return context;
    }

    /**
     * 获取当前激活的配置文件
     */
    private String getActiveProfile() {
        // TODO: 从Spring Environment中获取
        return "dev";
    }
}
